package com.mdd.front.service.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.annotation.Resource;
import com.mdd.common.entity.user.UserWxPhone;
import com.mdd.common.mapper.user.UserWxPhoneMapper;
import com.mdd.front.vo.user.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.easemob.im.server.model.EMUser;
import com.github.yulichang.query.MPJQueryWrapper;
import com.mdd.common.config.GlobalConfig;
import com.mdd.common.core.AjaxResult;
import com.mdd.common.entity.AppOrder;
import com.mdd.common.entity.UserFriend;
import com.mdd.common.entity.distribution.Distribution;
import com.mdd.common.entity.order.Order;
import com.mdd.common.entity.order.OrderAfter;
import com.mdd.common.entity.order.OrderGoods;
import com.mdd.common.entity.user.User;
import com.mdd.common.entity.user.UserAuth;
import com.mdd.common.entity.withdraw.WithdrawApply;
import com.mdd.common.enums.ClientEnum;
import com.mdd.common.enums.NoticeEnum;
import com.mdd.common.enums.OrderAfterEnum;
import com.mdd.common.enums.OrderEnum;
import com.mdd.common.enums.OrderGoodsEnum;
import com.mdd.common.enums.PaymentEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.AppOrderMapper;
import com.mdd.common.mapper.ExpressMapper;
import com.mdd.common.mapper.UserFriendMapper;
import com.mdd.common.mapper.distribution.DistributionMapper;
import com.mdd.common.mapper.order.OrderAfterMapper;
import com.mdd.common.mapper.order.OrderGoodsMapper;
import com.mdd.common.mapper.order.OrderMapper;
import com.mdd.common.mapper.user.UserAuthMapper;
import com.mdd.common.mapper.user.UserMapper;
import com.mdd.common.mapper.withdraw.WithdrawApplyMapper;
import com.mdd.common.plugin.notice.NoticeCheck;
import com.mdd.common.plugin.wechat.WxMnpDriver;
import com.mdd.common.util.ConfigUtils;
import com.mdd.common.util.HttpUtils;
import com.mdd.common.util.IpUtils;
import com.mdd.common.util.RedisUtils;
import com.mdd.common.util.StringUtils;
import com.mdd.common.util.TimeUtils;
import com.mdd.common.util.ToolUtils;
import com.mdd.common.util.UrlUtils;
import com.mdd.common.util.em.EMServiceUtil;
import com.mdd.front.service.IDistributionService;
import com.mdd.front.service.IUserService;
import com.mdd.front.validate.user.NewUserUpdateValidate;
import com.mdd.front.validate.user.UserBindWechatValidate;
import com.mdd.front.validate.user.UserPhoneBindValidate;
import com.mdd.front.vo.login.LoginTokenVo;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpUtil;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;

/**
 * 用户服务实现类
 */
@Service
public class UserServiceImpl implements IUserService {

	@Resource
	UserMapper userMapper;

	@Resource
	UserAuthMapper userAuthMapper;

	@Resource
	OrderMapper orderMapper;

	@Resource
	ExpressMapper expressMapper;

	@Resource
	OrderGoodsMapper orderGoodsMapper;

	@Resource
	DistributionMapper distributionMapper;

	@Resource
	OrderAfterMapper orderAfterMapper;

	@Resource
	WithdrawApplyMapper withdrawApplyMapper;

	@Resource
	IDistributionService iDistributionService;
	@Autowired
	private EMServiceUtil eMServiceUtil;
	@Autowired
	private UserFriendMapper userFriendMapper;
	@Autowired
	private AppOrderMapper appOrderMapper;

	@Autowired
	private UserWxPhoneMapper userWxPhoneMapper;
	private String exampleCode = "518186";

	/**
	 * 个人中心
	 *
	 * @author fzr
	 * @param userId 用户ID
	 * @return UserCenterVo
	 */
	@Override
	public UserCenterVo center(Integer userId, Integer terminal) {
		User user = userMapper.selectOne(new QueryWrapper<User>()
				.select("id,sn,avatar,real_name,nickname,username,mobile,money,is_new,code,earnings")
				.eq("id", userId)
				.last("limit 1"));

		UserCenterVo vo = new UserCenterVo();
		BeanUtils.copyProperties(user, vo);
//		if (user.getAvatar().equals("")) {
//			String avatar = ConfigUtils.get("user", "defaultAvatar", "");
//			vo.setAvatar(UrlUtils.toAbsoluteUrl(avatar));
//		} else {
//			vo.setAvatar(UrlUtils.toAbsoluteUrl(user.getAvatar()));
//		}

		vo.setIsBindWechat(false);
//		if (terminal.equals(ClientEnum.OA.getCode()) || terminal.equals(ClientEnum.MNP.getCode())) {
			UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
					.select("id,openid,terminal")
					.eq("user_id", userId)
					//.eq("terminal", terminal)
					.last("limit 1"));
			vo.setIsBindWechat((userAuth != null && StringUtils.isNotEmpty(userAuth.getOpenid())));
//		}

		// 订单统计
		// 待支付
		Long waitPayCount = orderMapper.selectCount(new QueryWrapper<Order>()
				.eq("user_id", userId)
				.eq("is_delete", 0)
				.eq("order_status", OrderEnum.ORDER_STATUS_WAIT_PAY.getCode())
				.eq("main_order", 1));
		// 待发货
		Long waitDeliveryCount = orderMapper.selectCount(new QueryWrapper<Order>()
				.eq("user_id", userId)
				.eq("is_delete", 0)
				.eq("main_order", 1)
				.eq("order_status", OrderEnum.ORDER_STATUS_WAIT_DELIVER.getCode()));
		// 待收货
		Long waitConfirmCount = orderMapper.selectCount(new QueryWrapper<Order>()
				.eq("user_id", userId)
				.eq("is_delete", 0)
				.eq("main_order", 1)
				.eq("order_status", OrderEnum.ORDER_STATUS_TAKE_DELIVER.getCode()));
		//待分享(1、普通用户只能分享购买过的商品 2、分销商能分享所有商品)
		Long shareCount = orderGoodsMapper.selectCount(new MPJQueryWrapper<OrderGoods>()
				.select("t.id")
				.innerJoin("?_order o ON o.id = t.order_id".replace("?_", GlobalConfig.tablePrefix))
				.innerJoin("?_distribution_goods dg ON t.goods_id=dg.goods_id".replace("?_", GlobalConfig.tablePrefix))
				.eq("o.order_status", OrderEnum.ORDER_STATUS_COMPLETED.getCode())
				.eq("t.user_id", userId)
				.eq("o.main_order", 1)
				.eq("dg.is_distribution", 1));


		// 商品评价统计
		Long waitCommentCount = orderGoodsMapper.selectCount(new MPJQueryWrapper<OrderGoods>()
				.select("t.id")
				.innerJoin("?_order o ON o.id = t.order_id".replace("?_", GlobalConfig.tablePrefix))
				.eq("o.order_status", OrderEnum.ORDER_STATUS_COMPLETED.getCode())
				.eq("t.user_id", userId)
				.eq("t.can_comment", 1)
				.eq("t.is_comment", 0));

		// 售后统计
		MPJQueryWrapper<OrderGoods> mpjQueryWrapper = new MPJQueryWrapper<>();
		mpjQueryWrapper.innerJoin("?_order o ON o.id=t.order_id".replace("?_", GlobalConfig.tablePrefix))
				.select("t.id")
				.eq("t.after_sale", OrderGoodsEnum.AFTER_STATUS_ING.getCode())
				.eq("o.user_id", userId)
				.eq("o.is_delete", 0)
				.eq("o.pay_is", PaymentEnum.OK_PAID.getCode())
				.gt("o.order_status", OrderEnum.ORDER_STATUS_WAIT_PAY.getCode())
				.lt("o.order_status", OrderEnum.ORDER_STATUS_CANCEL.getCode());
		Long waitAfterSaleCount = orderGoodsMapper.selectCount(mpjQueryWrapper);

		//物流订单统计
		//待开始
		//        Long expressWait=expressMapper.selectCount(new QueryWrapper<Express>()
		//                .eq("user_id", userId)
		//                .eq("is_delete", 0)
		//                .eq("express_status", OrderEnum.EXPRESS_STATUS_WAIT_DELIVER.getCode()));
		//        //进行中
		//        Long expressTake=expressMapper.selectCount(new QueryWrapper<Express>()
		//                .eq("user_id", userId)
		//                .eq("is_delete", 0)
		//                .eq("express_status", OrderEnum.EXPRESS_STATUS_TAKE_DELIVER.getCode()));
		//        //待支付
		//        Long expressWaitPay=expressMapper.selectCount(new QueryWrapper<Express>()
		//                .eq("user_id", userId)
		//                .eq("is_delete", 0)
		//                .eq("express_status", OrderEnum.EXPRESS_STATUS_WAIT_PAY.getCode()));
		//        //已完成
		//        Long expressCompleted=expressMapper.selectCount(new QueryWrapper<Express>()
		//                .eq("user_id", userId)
		//                .eq("is_delete", 0)
		//                .eq("express_status", OrderEnum.EXPRESS_STATUS_COMPLETED.getCode()));

		//物流订单统计
//		List<Integer> orderstatusList = new ArrayList<Integer>();
//		orderstatusList.add(0);
//		orderstatusList.add(1);
//		orderstatusList.add(2);
//		orderstatusList.add(10);
//		orderstatusList.add(200);
		//待开始 expressWait 0,1,2,10,200
		Long expressWait = appOrderMapper.selectCount(new LambdaQueryWrapper<AppOrder>()
				.eq(AppOrder::getUserid, userId)
				.eq(AppOrder::getPaystatus,1)
				.eq(AppOrder::getApporderstatus, 0).eq(AppOrder::getDelstate, 0));
		//进行中 expressTake 101,400
//		orderstatusList = new ArrayList<Integer>();
//		orderstatusList.add(101);
//		orderstatusList.add(400);
		Long expressTake = appOrderMapper.selectCount(new LambdaQueryWrapper<AppOrder>()
				.eq(AppOrder::getUserid, userId)
				.eq(AppOrder::getApporderstatus, 1).eq(AppOrder::getDelstate, 0));
		//待支付 expressWaitPay
		Long expressWaitPay = appOrderMapper.selectCount(new LambdaQueryWrapper<AppOrder>()
				.eq(AppOrder::getUserid, userId)
				.eq(AppOrder::getPaystatus,2).eq(AppOrder::getDelstate, 0));
		//已完成 expressCompleted 13,15
//		orderstatusList = new ArrayList<Integer>();
//		orderstatusList.add(13);
//		orderstatusList.add(15);
		Long expressCompleted = appOrderMapper.selectCount(new LambdaQueryWrapper<AppOrder>()
				.eq(AppOrder::getUserid, userId)
				.eq(AppOrder::getApporderstatus, 2).eq(AppOrder::getDelstate, 0));
		// 是否为分销会员
		vo.setIsDistribution(0);
		Distribution distribution = distributionMapper.selectOne(new QueryWrapper<Distribution>()
				.eq("user_id", userId));

		if (!ObjectUtils.isEmpty(distribution)) {
			//修改 因为这个表里的数据 等级为1代表不是会员
			if(distribution.getLevelId() > 1){
				vo.setIsDistribution(distribution.getLevelId() - 1);
			}
			if(null != distribution.getExpireTime()) {
				vo.setExpireTime(TimeUtils.millisecondToDate(distribution.getExpireTime() * 1000));
			}
			switch (distribution.getLevelId()) {
				case 2:
					vo.setLevelName("银牌会员");
					break;
				case 3:
					vo.setLevelName("金牌会员");
					break;
				case 4:
					vo.setLevelName("钻石会员");
					break;
				case 5:
					vo.setLevelName("合伙人");
					break;
				case 6:
					vo.setLevelName("联创V8");
					break;
				case 7:
					vo.setLevelName("联创V9");
					break;

				default:
					vo.setLevelName("普通用户");
					break;
			}
		}

		vo.setWaitPayCount(waitPayCount);
		vo.setWaitDeliveryCount(waitDeliveryCount);
		vo.setWaitConfirmCount(waitConfirmCount);
		vo.setShareCount(shareCount);
		vo.setWaitCommentCount(waitCommentCount);
		vo.setWaitAfterSaleCount(waitAfterSaleCount);

		vo.setExpressWaitCount(expressWait);
		vo.setExpressTakeCount(expressTake);
		vo.setExpressWaitPayCount(expressWaitPay);
		vo.setExpressCompletedCount(expressCompleted);
		return vo;
	}

	/**
	 * 个人信息
	 *
	 * @author fzr
	 * @param userId 用户ID
	 * @return UserInfoVo
	 */
	@Override
	public UserInfoVo info(Integer userId) {
		User user = userMapper.selectOne(new QueryWrapper<User>()
				.select("id,sn,avatar,real_name,nickname,username,mobile,password,sex,create_time,birthday,email,address,position,unit_name,tax_number,"
						+ "unit_address,unit_phone,bank_name,bank_card,is_auth")
				.eq("id", userId)
				.last("limit 1"));

		UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
				.select("id,openid")
				.eq("user_id", userId)
				.last("limit 1"));

		UserInfoVo vo = new UserInfoVo();
		BeanUtils.copyProperties(user, vo);
		vo.setIsPassword(!user.getPassword().equals(""));
		vo.setIsBindMnp(userAuth != null);
		vo.setVersion(GlobalConfig.version);
		vo.setCreateTime(TimeUtils.timestampToDate(user.getCreateTime()));

//		if (!user.getAvatar().equals("")) {
//			vo.setAvatar(UrlUtils.toAbsoluteUrl(user.getAvatar()));
//		} else {
//			String avatar = ConfigUtils.get("user", "defaultAvatar", "");
//			vo.setAvatar(UrlUtils.toAbsoluteUrl(avatar));
//		}

		return vo;
	}

	/**
	 * 编辑信息
	 *
	 * @author fzr
	 * @param updateValidate 参数
	 * @param userId 用户ID
	 */
	/*@Override
    public void edit(UserUpdateValidate updateValidate, Integer userId) {
        String field = updateValidate.getField();
        String value = updateValidate.getValue();

        switch (field) {
            case "avatar":
                User avatarUser = new User();
                avatarUser.setId(userId);
                avatarUser.setAvatar(UrlUtils.toRelativeUrl(value));
                avatarUser.setUpdateTime(System.currentTimeMillis() / 1000);
                userMapper.updateById(avatarUser);
                break;
            case "username":
                User usernameUser = userMapper.selectOne(new QueryWrapper<User>()
                        .select("id,username")
                        .eq("username", value)
                        .eq("is_delete", 0)
                        .last("limit 1"));

                if (StringUtils.isNotNull(usernameUser) && !usernameUser.getId().equals(userId)) {
                    throw new OperateException("账号已被使用!");
                }

                if (StringUtils.isNotNull(usernameUser) && usernameUser.getUsername().equals(value)) {
                    throw new OperateException("新账号与旧账号一致,修改失败!");
                }

                User u = new User();
                u.setId(userId);
                u.setUsername(value);
                u.setUpdateTime(System.currentTimeMillis() / 1000);
                userMapper.updateById(u);
                break;
            case "nickname":
                User nicknameUser = new User();
                nicknameUser.setId(userId);
                nicknameUser.setNickname(value);
                nicknameUser.setUpdateTime(System.currentTimeMillis() / 1000);
                userMapper.updateById(nicknameUser);
                break;
            case "sex":
                User sexUser = new User();
                sexUser.setId(userId);
                sexUser.setSex(Integer.parseInt(value));
                sexUser.setUpdateTime(System.currentTimeMillis() / 1000);
                userMapper.updateById(sexUser);
                break;
            default:
                throw new OperateException("不被支持的类型");
        }
    }*/
	@Override
	public void edit(User user, Integer userId) {
		if(StringUtils.isNotEmpty(user.getAvatar())) {
			user.setAvatar("https://kdkdkd.oss-cn-shanghai.aliyuncs.com/"+user.getAvatar());
		}
		user.setId(userId);
		user.setUpdateTime(System.currentTimeMillis() / 1000);
		userMapper.updateById(user);
	}

	/**
	 * 修改密码
	 *
	 * @author fzr
	 * @param password 新密码
	 * @param userId 用户ID
	 */
	@Override
	public void changePwd(String password, String oldPassword, Integer userId) {
		User user = userMapper.selectOne(new QueryWrapper<User>()
				.select("id,password,salt")
				.eq("id", userId)
				.eq("is_delete", 0)
				.last("limit 1"));

		Assert.notNull(user, "用户不存在");

		if (!user.getPassword().equals("")) {
			Assert.notNull(oldPassword, "oldPassword参数缺失");
			String oldPwd = ToolUtils.makeMd5(oldPassword.trim() + user.getSalt());
			if (!oldPwd.equals(user.getPassword())) {
				throw new OperateException("原密码不正确!");
			}
		}

		String salt = ToolUtils.randomString(5);
		String pwd  = ToolUtils.makeMd5(password.trim()+salt);

		User u = new User();
		u.setId(userId);
		u.setPassword(pwd);
		u.setSalt(salt);
		u.setUpdateTime(System.currentTimeMillis() / 1000);
		userMapper.updateById(u);
	}

	/**
	 * 忘记密码
	 *
	 * @author fzr
	 * @param password 新密码
	 * @param mobile 手机号
	 * @param code 验证码
	 */
	@Override
	public void forgotPwd(String password, String mobile, String code) {
		// 校验验证码
		int sceneCode = NoticeEnum.FORGOT_PASSWORD_CODE.getCode();
		if (!NoticeCheck.verify(sceneCode, code)) {
			throw new OperateException("验证码错误!");
		}

		// 查询手机号
		User user = userMapper.selectOne(new QueryWrapper<User>()
				.select("id,username,mobile,is_disable")
				.eq("is_delete", 0)
				.eq("mobile", mobile)
				.last("limit 1"));

		// 验证账号
		com.baomidou.mybatisplus.core.toolkit.Assert.notNull(user, "账号不存在!");

		String salt = ToolUtils.randomString(5);
		String pwd  = ToolUtils.makeMd5(password.trim()+salt);

		// 更新密码
		user.setPassword(pwd);
		user.setSalt(salt);
		user.setUpdateTime(System.currentTimeMillis() / 1000);
		userMapper.updateById(user);
	}

	/**
	 * 绑定手机
	 *
	 * @author fzr
	 * @param mobileValidate 参数
	 * @param userId 用户ID
	 */
	@Override
	public UserBindVo bindMobile(UserPhoneBindValidate mobileValidate, Integer userId) {
//		String type   = mobileValidate.getType();
		String mobile = mobileValidate.getMobile();
		String code   = mobileValidate.getCode().toLowerCase();

		// 校验验证码
		//        int sceneCode = type.equals("bind") ? NoticeEnum.BIND_MOBILE_CODE.getCode() : NoticeEnum.CHANGE_MOBILE_CODE.getCode() ;
		//        if (!NoticeCheck.verify(sceneCode, code)) {
		//            throw new OperateException("验证码错误!");
		//        }
		boolean right = false;
		Object savedMobile = RedisUtils.get("MOBILE_CODE_"+ 2 + "_" + code);
		if (savedMobile != null && mobile.equals(savedMobile.toString())) {
			right = true;
		}
		if(exampleCode.equals(code)){
			right = true;
		}
		Assert.isFalse(!right, "验证码不一致");

		User user = userMapper.selectOne(new QueryWrapper<User>()
				.eq("mobile", mobile)
				.eq("is_delete", 0)
				.last("limit 1"));

		//        if (StringUtils.isNotNull(user) && user.getId().equals(userId)) {
		//            throw new OperateException("手机号已被其它账号绑定!");
		//        }
		UserBindVo userBindVo = new UserBindVo();
		UserWxPhone userWxPhone = userWxPhoneMapper.selectOne(new QueryWrapper<UserWxPhone>()
				.eq("wx_phone", mobile)
				.last("limit 1"));
		if (StringUtils.isNotNull(user)) {
			//如果没有被注册过就直接下一步 如果被注册过了就要去查询绑定记录 绑定过了也不可以绑定了

			//-- 先省略查询绑定记录

			//如果绑定记录存在就不允许绑定 如果不存在就查看user表里面有没有用户号码相同的用户 如果绑定记录里有就肯定存在所以这个是不需要判断的
			//直接去查找当前登录用户的 user_auth记录 然后修改为用户表里手机号码为此号码的用户id到user_auth表里

			if(userWxPhone == null){
				UserAuth userAuth = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
						.eq("user_id", userId)
						.last("limit 1"));
				userAuth.setUserId(user.getId());
				userAuthMapper.updateById(userAuth);
				UserWxPhone saveEntity = new UserWxPhone();
				saveEntity.setUserId(user.getId());
				saveEntity.setWxPhone(mobile);
				userWxPhoneMapper.insert(saveEntity);
				BeanUtils.copyProperties(user, userBindVo);
				userBindVo.setSmsCode(code);
				RedisUtils.set("MOBILE_CODE_"+ 1 + "_" + code,mobile,300);
				return userBindVo;
			}else{
				throw new OperateException("手机号已被其它账号绑定!");
			}
		}else{
			if(userWxPhone != null){
				throw new OperateException("手机号已被其它账号绑定!");
			}
			User u = new User();
			u.setId(userId);
			u.setMobile(mobile);
			u.setUpdateTime(System.currentTimeMillis() / 1000);
			userMapper.updateById(u);
			UserWxPhone saveEntity = new UserWxPhone();
			saveEntity.setUserId(userId);
			saveEntity.setWxPhone(mobile);
			userWxPhoneMapper.insert(saveEntity);
			RedisUtils.set("MOBILE_CODE_"+ 1 + "_" + code,mobile,300);
			u = userMapper.selectById(u.getId());
			BeanUtils.copyProperties(u, userBindVo);
			userBindVo.setSmsCode(code);
			return userBindVo;
		}
	}

	public static JSONObject getopenid2(String code) {
		JSONObject jsonObject = new JSONObject();
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("appid", "wxac5ad4234319499d");
		params.put("secret", "3e5620b79041753e343f1be65da2c97f");
//		params.put("appid", "wx03d3a4501c174a80");
//		params.put("secret", "b5ba2c574608a0fa9a3d3a2f31202a13");
		params.put("grant_type", "authorization_code");
		params.put("code", code);
		String result = HttpUtil.get(
				"https://api.weixin.qq.com/sns/oauth2/access_token", params);
		if (result != null) {
			jsonObject = JSONObject.parseObject(result);
			return jsonObject;
		}
		return jsonObject;
	}

	public static void main(String[] args) throws WxErrorException {
				JSONObject getopenid2 = getopenid2("071se510026b6T1Ykf000fCar64se516");
				System.out.println(getopenid2);
//		WxMaService wxMaService = new WxMaServiceImpl();
//		WxMaDefaultConfigImpl wxConfig = new WxMaDefaultConfigImpl();
//		wxConfig.setSecret("b5ba2c574608a0fa9a3d3a2f31202a13");
//		wxConfig.setAppid("wx03d3a4501c174a80");
//		wxMaService.setWxMaConfig(wxConfig);
//		//         WxMaJscode2SessionResult sessionResult = wxMaService.getUserService().getSessionInfo("0b1Y9qHa1mNCEH0j9rHa1EK4tT2Y9qHH");
//		WxMaPhoneNumberInfo wxMaPhoneNumberInfo = wxMaService.getUserService().getNewPhoneNoInfo("0d16DqHa12VDEH0BldGa1OYL2z26DqHn");
//		System.out.println(wxMaPhoneNumberInfo.getPhoneNumber());
	}

	/**
	 * 微信手机号
	 *
	 * @author fzr
	 * @param code 获取手机号的Code
	 */
	@Override
	public LoginTokenVo mnpMobile(String code) {
		Map<String, String> config = ConfigUtils.get("mp_channel");
		WxMaService wxMaService = new WxMaServiceImpl();
		WxMaDefaultConfigImpl wxConfig = new WxMaDefaultConfigImpl();
		wxConfig.setSecret(config.getOrDefault("appSecret", ""));
		wxConfig.setAppid(config.getOrDefault("appId", ""));
		wxMaService.setWxMaConfig(wxConfig);
		System.out.println("进来接口code："+code);

		try {
			System.out.println("appId:"+wxConfig.getAppid());
			System.out.println("appSecret:"+wxConfig.getSecret());
			WxMaPhoneNumberInfo wxMaPhoneNumberInfo = wxMaService.getUserService().getNewPhoneNoInfo(code);
			//            WxMaJscode2SessionResult sessionResult = wxMaService.getUserService().getSessionInfo(code);
			//            System.out.println(sessionResult.getOpenid());
			//            System.out.println(sessionResult.getUnionid());
			//            Integer userId = LikeFrontThreadLocal.getUserId();
			//            User user = new User();
			//            user.setId(userId);
			//            user.setMobile(wxMaPhoneNumberInfo.getPhoneNumber());
			//            user.setUpdateTime(System.currentTimeMillis() / 1000);
			//            userMapper.updateById(user);
			String mobile = wxMaPhoneNumberInfo.getPhoneNumber();
			User user = userMapper.selectOne(new QueryWrapper<User>()
					.select("id,username,password,salt,mobile,is_disable,is_new,em_username")
					.eq("mobile", mobile)
					.eq("is_delete", 0)
					.eq("is_close",0)
					.last("limit 1"));
			if(null == user) { // 注册
				Integer sn  = this.__generateSn();
				String salt = ToolUtils.randomString(5);
				String pwd  = ToolUtils.makeMd5("123456"+salt);
				// 邀请码 
				String code1 = userMapper.randMakeOrderSn("code");
				user = new User();
				user.setSn(sn);
				user.setNickname("用户"+sn);
				user.setMobile(mobile);
				user.setUsername(mobile);
				user.setPassword(pwd);
				user.setSalt(salt);
				user.setAvatar("/api/static/default_avatar.png");
				user.setChannel(1);
				user.setIsNew(1);
				user.setCreateTime(System.currentTimeMillis() / 1000);
				user.setUpdateTime(System.currentTimeMillis() / 1000);
				user.setCode(code1);
				user.setAncestorRelation("");
				userMapper.insert(user);
				// 分销信息
				iDistributionService.addDistributionData(user.getId());

				// 创建环信账号
				String nickName = this.__EMUserName();
				EMUser createUser = eMServiceUtil.createUser(nickName);
				Assert.notNull(createUser, "登录失败");
				user.setEmUsername(createUser.getUsername());
				user.setEmPassword(createUser.getUsername());
				userMapper.updateById(user);
				// 绑定通讯里的用户信息
			}else if(StringUtils.isEmpty(user.getEmUsername())){
				// 创建环信账号
				String nickName = this.__EMUserName();
				EMUser createUser = eMServiceUtil.createUser(nickName);
				Assert.notNull(createUser, "登录失败");
				user.setEmUsername(createUser.getUsername());
				user.setEmPassword(createUser.getUsername());
				userMapper.updateById(user);
			}
			// 绑定userId
			Integer userId = user.getId();
			List<UserFriend> list = userFriendMapper.selectList(new LambdaQueryWrapper<UserFriend>().eq(UserFriend::getPhone, mobile).select(UserFriend::getId,UserFriend::getUid,UserFriend::getPhone
					,UserFriend::getUserId));
			if(CollectionUtil.isNotEmpty(list)) {
				list.stream().forEach(friend ->{
					if(null == friend.getUserId()) {
						friend.setUserId(userId);
						friend.setUpdateTime(TimeUtils.timestamp());
						userFriendMapper.updateById(friend);

						//添加第二条记录
						UserFriend userFriendOther = new UserFriend();
						User userOther = userMapper.selectOne(new QueryWrapper<User>()
								.eq("id", friend.getUid())
								.last("limit 1"));
						userFriendOther.setUid(friend.getUserId());
						userFriendOther.setUserId(friend.getUid());
						userFriendOther.setCreateTime(System.currentTimeMillis() / 1000);
						userFriendOther.setUpdateTime(System.currentTimeMillis() / 1000);
						userFriendOther.setName(userOther.getNickname());
						userFriendOther.setPhone(userOther.getMobile());
						userFriendOther.setAddress(userOther.getAddress());
						userFriendMapper.insert(userFriendOther);

					}
				});
			}else {
				UserFriend userFriend = new UserFriend();
				userFriend.setUserId(userId);
				userFriend.setName(user.getNickname());
				userFriend.setPhone(user.getMobile());
				userFriend.setCreateTime(TimeUtils.timestamp());
				userFriendMapper.insert(userFriend);
			}
			return this.__loginToken(user.getId(), user.getMobile(), user.getIsNew(), 1,user.getEmUsername());

		} catch (WxErrorException e) {
			throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
		}
	}

	/**
	 * 处理录令牌
	 *
	 * @author fzr
	 * @param userId 用户ID
	 * @param mobile 用户手机
	 * @param terminal 终端
	 * @return LoginTokenVo
	 */
	private LoginTokenVo __loginToken(Integer userId, String mobile, Integer isNew, Integer terminal,String emUsername) {
		// 实现账号登录
		StpUtil.kickout(userId, String.valueOf(terminal));
		StpUtil.login(userId, String.valueOf(terminal));

		// 更新登录信息
		User user = new User();
		user.setLastLoginIp(IpUtils.getHostIp());
		user.setLastLoginTime(System.currentTimeMillis() / 1000);
		userMapper.update(user, new QueryWrapper<User>().eq("id", userId));
		// 返回登录信息
		LoginTokenVo vo = new LoginTokenVo();
		vo.setId(userId);
		vo.setIsBindMobile(!StringUtils.isEmpty(mobile));
		vo.setToken(StpUtil.getTokenValue());
		vo.setIsNew(isNew);
		vo.setEmUsername(emUsername);
		vo.setEmPassword(emUsername);
		return vo;
	}


	/**
	 * 更新新用户昵称头像等信息
	 *
	 * @param newUserUpdateValidate 参数
	 * @param userId 用户id
	 */
	@Override
	public void updateNewUserInfo(NewUserUpdateValidate newUserUpdateValidate, Integer userId) {
		User user = new User();
		user.setId(userId);
		user.setNickname(newUserUpdateValidate.getNickname());
		user.setAvatar(UrlUtils.toRelativeUrl(newUserUpdateValidate.getAvatar()));
		user.setIsNew(0);
		user.setUpdateTime(System.currentTimeMillis() / 1000);
		userMapper.updateById(user);
	}

	/**
	 * 绑定小程序
	 *
	 * @param bindMnpValidate 参数
	 * @param userId 用户ID
	 */
	@Override
	public void bindMnp(UserBindWechatValidate bindMnpValidate, Integer userId) {
		try {
			// 通过code获取微信信息
			String code = bindMnpValidate.getCode();
			WxMaService wxMaService = WxMnpDriver.mnp();

			WxMaJscode2SessionResult sessionResult = wxMaService.getUserService().getSessionInfo(code);
			String openId = sessionResult.getOpenid();
			String uniId = sessionResult.getUnionid();
			String unionId = uniId;

			System.out.println("绑定小程序的code："+code);
			System.out.println("绑定小程序的openId:"+openId);
			System.out.println("绑定小程序的uniId:"+uniId);

			// 授权校验,未授权创建授权，已授权返回
			bindWechatAuth(openId, unionId, ClientEnum.MNP.getCode(), userId);

		} catch (WxErrorException e) {
			throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
		}
	}
	
	@Override
	public void bindAppWechat(UserBindWechatValidate bindAppValidate, Integer userId) {
		try {
			// 通过code获取微信信息
			String code = bindAppValidate.getCode();
			System.out.println("获取到的code："+code);
			
			JSONObject result = getopenid2(code);
			
			System.out.println("微信返回的结果："+result);
			
			// 授权校验,未授权创建授权，已授权返回
			bindWechatAuth(result.getString("openid"), result.getString("unionid"), ClientEnum.APK.getCode(), userId);
		} catch (Exception e) {
			e.printStackTrace();
			throw new OperateException(e.getMessage());
		}
	}

	/**
	 * 绑定公众号
	 *
	 * @param bindOaValidate 参数
	 * @param userId 用户ID
	 */
	@Override
	public void bindOa(UserBindWechatValidate bindOaValidate, Integer userId) {
		try {
			// 通过code获取微信信息
			WxMpService wxMpService = WxMnpDriver.oa();
			WxOAuth2AccessToken wxOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(bindOaValidate.getCode());
			String uniId = wxOAuth2AccessToken.getUnionId();
			String openId  = wxOAuth2AccessToken.getOpenId();
			String unionId = uniId == null ? "0" : uniId;

			// 授权校验,未授权创建授权，已授权返回
			bindWechatAuth(openId, unionId, ClientEnum.OA.getCode(), userId);

		} catch (WxErrorException e) {
			throw new OperateException(e.getError().getErrorCode() + ", " + e.getError().getErrorMsg());
		}
	}

	/**
	 * 注销账户
	 *
	 * @param userId 用户ID
	 */
	@Override
	public List<Map<String, Object>> cancellation(Integer userId) {
		List<Map<String, Object>> linkedList = new LinkedList<>();
		QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
		userQueryWrapper.eq("id", userId);
		userQueryWrapper.eq("is_delete",0);
		userQueryWrapper.last("limit 1");
		User user = userMapper.selectOne(userQueryWrapper);
		Assert.notNull(user, "该用户不存在！");

		List<Integer> errorOrderStatusList = Arrays.asList(
				OrderEnum.ORDER_STATUS_WAIT_PAY.getCode(),
				OrderEnum.ORDER_STATUS_WAIT_DELIVER.getCode(),
				OrderEnum.ORDER_STATUS_TAKE_DELIVER.getCode());

		QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
		queryWrapper.in("order_status",errorOrderStatusList);
		queryWrapper.eq("is_delete",0);
		queryWrapper.eq("user_id", userId);
		queryWrapper.last("limit 1");
		List<Order> orderList = orderMapper.selectList(queryWrapper);
		if (!orderList.isEmpty()){
			Map<String, Object> map = new LinkedHashMap<>();
			map.put("code",1);
			map.put("title","存在未完成订单");
			map.put("content","发现你的账号内有未处理完成的商城订单，待完成后可重新提交申请。");
			linkedList.add(map);
		}

		QueryWrapper<OrderAfter> orderAfterQueryWrapper = new QueryWrapper<>();
		orderAfterQueryWrapper.eq("is_delete",0);
		orderAfterQueryWrapper.eq("user_id", userId);
		orderAfterQueryWrapper.eq("after_status",OrderAfterEnum.AFTER_STATUS_ING.getCode());
		List<OrderAfter> orderAfterList = orderAfterMapper.selectList(orderAfterQueryWrapper);
		if (!orderAfterList.isEmpty()){
			Map<String, Object> map = new LinkedHashMap<>();
			map.put("code",2);
			map.put("title","存在售后中订单");
			map.put("content","发现你的账号内有订单处于售后中，待商家处理完成后可重新提交申请。");
			linkedList.add(map);
		}

		QueryWrapper<WithdrawApply> withdrawApplyQueryWrapper = new QueryWrapper<>();
		withdrawApplyQueryWrapper.eq("is_delete",0);
		withdrawApplyQueryWrapper.in("status",Arrays.asList(1,2));
		withdrawApplyQueryWrapper.eq("user_id", userId);
		List<WithdrawApply> withdrawApplyList = withdrawApplyMapper.selectList(withdrawApplyQueryWrapper);

		if (!withdrawApplyList.isEmpty()){
			Map<String, Object> map = new LinkedHashMap<>();
			map.put("code",3);
			map.put("title","存在佣金待提现申请");
			map.put("content","发现你的账号内有佣金处于提现中，待商家处理完成后可重新提交申请。");
			linkedList.add(map);
		}
		if (linkedList.isEmpty()){
			Map<String, Object> map = new LinkedHashMap<>();
			map.put("code",0);
			map.put("content","注销成功！");
			linkedList.add(map);
			// 把用户设置为注销状态
			user.setIsClose(1);
			// 清空用户手机号
			user.setMobile("");
			user.setUpdateTime(System.currentTimeMillis() / 1000);
			user.setDeleteTime(System.currentTimeMillis() / 1000);
			userMapper.updateById(user);
			// 查询是否绑定小程序或公众号
			QueryWrapper<UserAuth> userAuthQueryWrapper = new QueryWrapper<>();
			userAuthQueryWrapper.eq("user_id", userId);
			List<UserAuth> userAuthList = userAuthMapper.selectList(userAuthQueryWrapper);
			// 清除openid
			if (!userAuthList.isEmpty()){
				for (UserAuth userAuth : userAuthList) {
					userAuthMapper.deleteById(userAuth);
				}
			}
			// 修改分销功能
			Distribution distribution = distributionMapper.selectOne(new QueryWrapper<Distribution>()
					.eq("user_id", userId)
					.eq("is_delete", 0)
					.last("limit 1"));

			if (null != distribution){
				// 冻结分销商
				distribution.setIsFreeze(1);
				// 锁定分销商不能修改
				distribution.setIsClose(1);
				distribution.setUpdateTime(System.currentTimeMillis() / 1000);
				distributionMapper.updateById(distribution);
			}

			// 查询是否有下级分销用户
			QueryWrapper<User> queryUserWrapper = new QueryWrapper<>();
			queryUserWrapper.eq("first_leader", userId)
					.or()
					.eq("second_leader", userId)
					.or()
					.eq("third_leader", userId);
			queryUserWrapper.eq("is_delete",0);
			queryUserWrapper.eq("is_close", 0);
			List<User> distributionUserList = userMapper.selectList(queryUserWrapper);
			if (!distributionUserList.isEmpty()){
				// 取消所有下级用户
				for (User distributionUser : distributionUserList) {
					if (distributionUser.getFirstLeader().equals(userId)){
						distributionUser.setFirstLeader(0);
						// distributionUser.setIsLockLeader(1);
					}
					if (distributionUser.getSecondLeader().equals(userId)){
						distributionUser.setSecondLeader(0);
						// distributionUser.setIsLockLeader(1);
					}
					if (distributionUser.getThirdLeader().equals(userId)){
						distributionUser.setThirdLeader(0);
						// distributionUser.setIsLockLeader(1);
					}
					userMapper.updateById(distributionUser);
				}
			}
			// 将分销重置为系统
			user.setFirstLeader(0);
			user.setSecondLeader(0);
			user.setThirdLeader(0);
			userMapper.updateById(user);
		}
		return linkedList;
	}

	/**
	 * 绑定微信授权
	 *
	 * @param openId openId
	 * @param unionId unionId
	 * @param terminal 客户端端
	 * @param userId 用户ID
	 */
	public void bindWechatAuth(String openId, String unionId, Integer terminal, Integer userId) {
		// 授权表中查找授权记录
		UserAuth userAuthOpenId = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
				.eq("openid", openId)
				.last("limit 1"));
		boolean flag = false;
		if (userAuthOpenId != null) {
			// 该微信已绑定
			if(!userId.equals(userAuthOpenId.getUserId())) {
				User u = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userAuthOpenId.getUserId()));
				if(null != u && StringUtils.isEmpty(u.getMobile())) {
					userMapper.deleteById(userAuthOpenId.getUserId());
					userAuthMapper.deleteById(userAuthOpenId.getId());
					flag = true;
				}else {
					throw new OperateException("该微信已绑定");
				}
			}
			
		}else {
			flag = true;
		}
		
		if(flag) {
			// 记录微信授权
			UserAuth authModel = new UserAuth();
			authModel.setUserId(userId);
			authModel.setUnionid(unionId);
			authModel.setOpenid(openId);
			authModel.setTerminal(terminal);
			authModel.setCreateTime(System.currentTimeMillis() / 1000);
			authModel.setUpdateTime(System.currentTimeMillis() / 1000);
			userAuthMapper.insert(authModel);
		}

		// 已有授权，返回已绑定微信。 没有授权，绑定微信
//		if (!StringUtils.isBlank(unionId)) {
//			UserAuth userAuthUnionId = userAuthMapper.selectOne(new QueryWrapper<UserAuth>()
//					.eq("unionid", unionId)
//					.last("limit 1"));
//
//			if (userAuthUnionId != null && !userId.equals(userAuthUnionId.getUserId())) {
//				// 该微信已绑定
//				throw new OperateException("该微信已绑定");
//			}
//		}
	}

	@Override
	public AjaxResult<UserEmVo> getUserEmUsername(Integer userId) {
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getEmUsername,User::getEmPassword));
		Assert.notNull(user, "用户不存在");
		UserEmVo v = new UserEmVo();
		v.setEmUsername(user.getEmUsername());
		v.setEmPassword(user.getEmPassword());
		return AjaxResult.success(v);
	}

	/**
	 * 生成用户编号
	 *
	 * @author fzr
	 * @return Integer
	 */
	private Integer __generateSn() {
		Integer sn;
		while (true) {
			sn = Integer.parseInt(ToolUtils.randomInt(8));
			User snModel = userMapper.selectOne(new QueryWrapper<User>()
					.select("id,sn")
					.eq("sn", sn)
					.last("limit 1"));
			if (snModel == null) {
				break;
			}
		}
		return sn;
	}

	/**
	 * 	生成 环信 username
	 * @return
	 */
	public String __EMUserName() {
		String english ="abcdefghijklmnopqrstuvwxyz";
		String hybrid = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb=new StringBuffer();
		for(int i=0;i<6;i++){
			int number= random.nextInt(36);
			if(i == 0) {
				sb.append(english.charAt(random.nextInt(26)));
				continue;
			}
			sb.append(hybrid.charAt(number));
		}
		return sb.toString();

	}

	@Override
	public AjaxResult<Object> realNameAuthentication(User user) {
		Long count = userMapper.selectCount(new LambdaQueryWrapper<User>().eq(User::getId, user.getId()));
		if(count <= 0) {
			return AjaxResult.failed("用户不存在");
		}
		try {
			// 图片转base64
			String imgConvertBase64 = ToolUtils.imgConvertBase64(user.getFrontView());
			// 人脸验证
			String result = HttpUtils.postFormUrlencoded(user.getIdCard(), user.getRealName(), imgConvertBase64);
			if("success".equals(result)) {
				userMapper.updateById(user);
				return AjaxResult.success();
			}
			return AjaxResult.failed(result);
		} catch (Exception e) {
			e.printStackTrace();
			throw new OperateException(e.getMessage());
		}
	}

	@Override
	public AjaxResult<UserAuthVo> getAuthenticationInfo(Integer userId) {
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getRealName,
				User::getIdCard,User::getFrontView,User::getBackView));
		Assert.notNull(user, "用户不存在");
		UserAuthVo auth = new UserAuthVo();
		auth.setRealName(user.getRealName());
		auth.setIdCard(user.getIdCard());
		auth.setFrontView(user.getFrontView());
		auth.setBackView(user.getBackView());
		return AjaxResult.success(auth);
	}

	@Override
	public AjaxResult<Object> operateMsgNotify(Integer userId) {
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getIsMsg));
		Assert.notNull(user, "用户不存在");
		if(null == user.getIsMsg() || user.getIsMsg() == 0) {
			user.setIsMsg(1);
		}else {
			user.setIsMsg(0);
		}
		userMapper.updateById(user);
		return AjaxResult.success();
	}

	@Override
	public void updateUserPhoneInfo(String mobile, String mobileCode, Integer userId) {
		boolean right = false;
		Object savedMobile = RedisUtils.get("MOBILE_CODE_"+ 1 + "_" + mobileCode);
		if (savedMobile != null && mobile.equals(savedMobile.toString())) {
			right = true;
		}
		if(exampleCode.equals(mobileCode)){
			right = true;
		}
		Assert.isFalse(!right, "验证码不一致");
		
		Long count = userMapper.selectCount(new LambdaQueryWrapper<User>().eq(User::getMobile, mobile)
				.eq(User::getIsDelete, 0).eq(User::getIsClose, 0));
		if(count > 0) {
			throw new OperateException("该手机号码已被注册");
		}
		User user = new User();
		user = userMapper.selectById(userId);
		user.setUsername(mobile);
		user.setMobile(mobile);
		userMapper.updateById(user);
	}

	@Override
	public AjaxResult<Object> qryMsgNotify(Integer userId) {
		User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getId, userId).select(User::getId,User::getIsMsg));
		Assert.notNull(user, "用户不存在");
		if(null == user.getIsMsg()) {
			user.setIsMsg(1);
		}
		Map<String,Object> map = new HashMap<String, Object>();
		map.put("isMsg", user.getIsMsg());
		return AjaxResult.success(map);
	}

}
